﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Data;
using System.Windows.Input;

namespace LumenLiquid_Tool
{
    class Backdrop : DependencyObject
    {
        #region Classes

        public class SSkill : DependencyObject
        {
            public static readonly DependencyProperty SkillNameProperty =
                DependencyProperty.Register("SkillName", typeof(string), typeof(SSkill), new PropertyMetadata(default(string)));

            public string SkillName
            {
                get { return (string)GetValue(SkillNameProperty); }
                set { SetValue(SkillNameProperty, value); }
            }

            public static readonly DependencyProperty SkillDescriptionProperty =
                DependencyProperty.Register("SkillDescription", typeof(string), typeof(SSkill), new PropertyMetadata(default(string)));

            public string SkillDescription
            {
                get { return (string)GetValue(SkillDescriptionProperty); }
                set { SetValue(SkillDescriptionProperty, value); }
            }

            public Guid Guid { get; private set; }

            public SSkill()
            {
                Guid = Guid.NewGuid();
            }
        }

        public class SProfession : DependencyObject
        {
            public static readonly DependencyProperty NameProperty =
                DependencyProperty.Register("Name", typeof(string), typeof(SProfession), new PropertyMetadata(default(string)));

            public string Name
            {
                get { return (string)GetValue(NameProperty); }
                set { SetValue(NameProperty, value); }
            }

            public static readonly DependencyProperty DescriptionProperty =
                DependencyProperty.Register("Description", typeof(string), typeof(SProfession), new PropertyMetadata(default(string)));

            public string Description
            {
                get { return (string)GetValue(DescriptionProperty); }
                set { SetValue(DescriptionProperty, value); }
            }

            public static readonly DependencyProperty SkillsProperty =
                DependencyProperty.Register("Skills", typeof(ObservableCollection<SProfessionSkill>), typeof(SProfession), new PropertyMetadata(new ObservableCollection<SProfessionSkill>()));

            public ObservableCollection<SProfessionSkill> Skills
            {
                get { return (ObservableCollection<SProfessionSkill>)GetValue(SkillsProperty); }
                set { SetValue(SkillsProperty, value); }
            }

            public class SProfessionSkill : DependencyObject
            {
                public static readonly DependencyProperty SkillProperty =
                    DependencyProperty.Register("Skill", typeof(SSkill), typeof(SProfessionSkill),
                                                               new PropertyMetadata(default(SSkill)));

                public SSkill Skill
                {
                    get { return (SSkill)GetValue(SkillProperty); }
                    set { SetValue(SkillProperty, value); }
                }

                public static readonly DependencyProperty MaximumProperty =
                    DependencyProperty.Register("Maximum", typeof(int), typeof(SProfessionSkill),
                                                               new PropertyMetadata(12));

                public int Maximum
                {
                    get { return (int)GetValue(MaximumProperty); }
                    set { SetValue(MaximumProperty, value); }
                }

                public static readonly DependencyProperty MinimumProperty =
                    DependencyProperty.Register("Minimum", typeof(int), typeof(SProfessionSkill),
                                                               new PropertyMetadata(0));

                public int Minimum
                {
                    get { return (int)GetValue(MinimumProperty); }
                    set { SetValue(MinimumProperty, value); }
                }

                public static readonly DependencyProperty ValueProperty =
                    DependencyProperty.Register("Value", typeof(int), typeof(SProfessionSkill),
                                                               new PropertyMetadata(6));

                public int Value
                {
                    get { return (int)GetValue(ValueProperty); }
                    set { SetValue(ValueProperty, value); }
                }
            }
        }
        #endregion

        #region Properties
        public static readonly DependencyProperty GameTitleProperty =
            DependencyProperty.Register("GameTitle", typeof(string), typeof(Backdrop), new PropertyMetadata(""));

        public string GameTitle
        {
            get { return (string)GetValue(GameTitleProperty); }
            set { SetValue(GameTitleProperty, value); }
        }

        public static readonly DependencyProperty LanguagesProperty =
            DependencyProperty.Register("Languages", typeof(ObservableCollection<CultureInfo>), typeof(Backdrop), new PropertyMetadata(new ObservableCollection<CultureInfo>()));

        public ObservableCollection<CultureInfo> Languages
        {
            get { return (ObservableCollection<CultureInfo>)GetValue(LanguagesProperty); }
            set { SetValue(LanguagesProperty, value); }
        }

        public static readonly DependencyProperty SkillsProperty =
            DependencyProperty.Register("Skills", typeof(ObservableCollection<SSkill>), typeof(Backdrop), new PropertyMetadata(new ObservableCollection<SSkill>()));

        public ObservableCollection<SSkill> Skills
        {
            get { return (ObservableCollection<SSkill>)GetValue(SkillsProperty); }
            set { SetValue(SkillsProperty, value); }
        }

        public static readonly DependencyProperty ProfessionsProperty =
            DependencyProperty.Register("Professions", typeof(ObservableCollection<SProfession>), typeof(Backdrop), new PropertyMetadata(new ObservableCollection<SProfession>()));

        public ObservableCollection<SProfession> Professions
        {
            get { return (ObservableCollection<SProfession>)GetValue(ProfessionsProperty); }
            set { SetValue(ProfessionsProperty, value); }
        }
        #endregion

        #region UICommands

        #region CommandBindings
        public static CommandBinding AddProfessionCommand { get; private set; }
        public static CommandBinding RemoveProfessionCommand { get; private set; }
        public static CommandBinding AddSkillCommand { get; private set; }
        public static CommandBinding RemoveSkillCommand { get; private set; }
        #endregion

        #region RoutedUICommands
        public static RoutedUICommand AddProfession { get; set; }
        public static RoutedUICommand RemoveProfession { get; set; }
        public static RoutedUICommand AddSkill { get; set; }
        public static RoutedUICommand RemoveSkill { get; set; }
        #endregion

        #region Execute
        private static void AddProfessionExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            var backdrop = (Backdrop) e.Parameter;

            var profession = new SProfession();
            profession.Name = "Profession Name";
            profession.Skills = new ObservableCollection<SProfession.SProfessionSkill>();

            foreach (var professionSkill in backdrop.Skills.Select(skill => new SProfession.SProfessionSkill { Skill = skill }))
            {
                profession.Skills.Add(professionSkill);
            }

            backdrop.Professions.Add(profession);
        }

        private static void RemoveProfessionExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            var backdrop = (Backdrop) e.Parameter;

            var lcv = (ListCollectionView)CollectionViewSource.GetDefaultView(backdrop.Professions);

            backdrop.Professions.RemoveAt(lcv.CurrentPosition);
        }

        private static void AddSkillExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            var backdrop = (Backdrop) e.Parameter;

            var skill = new Backdrop.SSkill { SkillDescription = "", SkillName = "Empty" };

            backdrop.Skills.Add(skill);

            foreach (var profession in backdrop.Professions)
            {
                profession.Skills.Add(new SProfession.SProfessionSkill { Skill = skill });
            }
        }

        private static void RemoveSkillExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            var backdrop = (Backdrop) e.Parameter;
            var skill = (SSkill)((ListCollectionView)CollectionViewSource.GetDefaultView(backdrop.Skills)).CurrentItem;

            backdrop.Skills.Remove(skill);

            foreach (var profession in backdrop.Professions)
            {
                var profSkill = profession.Skills.First(s => s.Skill.Guid.Equals((skill).Guid));

                if (profSkill != null)
                    profession.Skills.Remove(profSkill);
            }
        }
        #endregion

        #region CanExecute
        private static void AddProfessionCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        private static void RemoveProfessionCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            var backdrop = (Backdrop) e.Parameter;

            var lcv = (ListCollectionView)CollectionViewSource.GetDefaultView(backdrop.Professions);

            e.CanExecute = lcv.CurrentPosition >= 0;
        }

        private static void AddSkillCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        private static void RemoveSkillCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            var backdrop = (Backdrop) e.Parameter;

			var lcv = (ListCollectionView)CollectionViewSource.GetDefaultView(backdrop.Skills);

            e.CanExecute = lcv.CurrentPosition >= 0;
        }
        #endregion
        #endregion

        static Backdrop()
        {
            AddProfession = new RoutedUICommand("", "add_prof", typeof(Backdrop));
            AddProfessionCommand = new CommandBinding(AddProfession, AddProfessionExecuted, AddProfessionCanExecute);
            RemoveProfession = new RoutedUICommand("", "rem_prof", typeof(Backdrop));
            RemoveProfessionCommand = new CommandBinding(RemoveProfession, RemoveProfessionExecuted, RemoveProfessionCanExecute);
            AddSkill = new RoutedUICommand("", "add_skill", typeof(Backdrop));
            AddSkillCommand = new CommandBinding(AddSkill, AddSkillExecuted, AddSkillCanExecute);
            RemoveSkill = new RoutedUICommand("", "rem_skill", typeof(Backdrop));
            RemoveSkillCommand = new CommandBinding(RemoveSkill, RemoveSkillExecuted, RemoveSkillCanExecute);
        }
    }
}
